const BaseStrategy = require('../base/BaseStrategy')

/**
 * 市场共振策略
 *
 * 检测多个时间框架和多个指标的共振信号
 * 当市场在多个维度上显示相同方向的信号时触发
 */
class MarketResonanceStrategy extends BaseStrategy {
  constructor (config = {}) {
    const defaultConfig = {
      priority: 90,
      parameters: {
        minResonanceStrength: 0.7,
        minAlignedTimeframes: 2,
        minAlignedIndicators: 2,

        timeframes: {
          '15m': { weight: 0.2 },
          '1h': { weight: 0.3 },
          '4h': { weight: 0.35 },
          '1d': { weight: 0.4 }
        },

        indicators: {
          'macd': { weight: 0.4 },
          'kdj': { weight: 0.3 },
          'ema': { weight: 0.3 }
        },

        resonanceTypes: {
          FULL: { minStrength: 0.85, weight: 1.0, positionMultiplier: 1.2 },
          STRONG: { minStrength: 0.75, weight: 0.9, positionMultiplier: 1.0 },
          MODERATE: { minStrength: 0.6, weight: 0.7, positionMultiplier: 0.8 },
          WEAK: { minStrength: 0.45, weight: 0.5, positionMultiplier: 0.6 }
        }
      }
    }

    super('market_resonance', { ...defaultConfig, ...config })
    this.resonanceStats = {
      resonanceTypeCount: {},
      avgResonanceStrength: 0
    }
  }

  checkConditions (marketData, analysisData) {
    if (!this.validateMarketData(marketData, analysisData)) {
      return false
    }

    const resonanceStrength = this.calculateResonanceStrength(marketData, analysisData)
    if (resonanceStrength < this.config.parameters.minResonanceStrength) {
      return false
    }

    if (!this.checkDirectionalBias(marketData, analysisData)) {
      return false
    }

    const alignedTimeframes = this.getAlignedTimeframes(marketData, analysisData)
    const alignedIndicators = this.getAlignedIndicators(marketData, analysisData)

    return alignedTimeframes.length >= this.config.parameters.minAlignedTimeframes &&
           alignedIndicators.length >= this.config.parameters.minAlignedIndicators
  }

  generateSignal (marketData, analysisData) {
    const resonanceAnalysis = this.analyzeResonance(marketData, analysisData)
    const direction = this.determineDirection(marketData, analysisData)
    const confidence = this.calculateConfidence(resonanceAnalysis)
    const positionRate = this.calculatePositionRate(resonanceAnalysis, confidence)

    return {
      type: direction,
      reason: `市场共振-${resonanceAnalysis.type}-强度${resonanceAnalysis.strength.toFixed(2)}`,
      confidence,
      positionRate,
      canReverse: false,
      level: this.calculateResonanceLevel(resonanceAnalysis),
      metadata: {
        resonanceType: resonanceAnalysis.type,
        resonanceStrength: resonanceAnalysis.strength,
        affectedTimeframes: resonanceAnalysis.timeframes,
        affectedIndicators: resonanceAnalysis.indicators
      }
    }
  }

  calculateResonanceStrength (marketData, analysisData) {
    const { timeframes, indicators } = this.config.parameters
    let totalWeight = 0
    let alignedWeight = 0

    Object.keys(timeframes).forEach(timeframe => {
      Object.keys(indicators).forEach(indicator => {
        const weight = timeframes[timeframe].weight * indicators[indicator].weight
        totalWeight += weight

        if (this.isIndicatorAligned(marketData, analysisData, timeframe, indicator)) {
          alignedWeight += weight
        }
      })
    })

    return totalWeight > 0 ? alignedWeight / totalWeight : 0
  }

  analyzeResonance (marketData, analysisData) {
    const strength = this.calculateResonanceStrength(marketData, analysisData)
    const alignedTimeframes = this.getAlignedTimeframes(marketData, analysisData)
    const alignedIndicators = this.getAlignedIndicators(marketData, analysisData)
    const resonanceType = this.classifyResonanceType(strength)

    return {
      strength,
      type: resonanceType,
      typeConfig: this.config.parameters.resonanceTypes[resonanceType],
      timeframes: alignedTimeframes,
      indicators: alignedIndicators
    }
  }

  isIndicatorAligned (marketData, analysisData, timeframe, indicator) {
    const direction = this.determineDirection(marketData, analysisData)

    if (direction === 'BUY') {
      return this.isIndicatorBullish(marketData, analysisData, timeframe, indicator)
    } else {
      return this.isIndicatorBearish(marketData, analysisData, timeframe, indicator)
    }
  }

  isIndicatorBullish (marketData, analysisData, timeframe, indicator) {
    const marketKey = `${indicator}${timeframe}Good`
    if (marketData[marketKey] === true) return true

    const analysisInfo = analysisData[`analysisInfo${timeframe}`]
    if (!analysisInfo) return false

    switch (indicator) {
      case 'macd':
        return analysisInfo.macd > 0 && analysisInfo.macdUpDays >= 1
      case 'kdj':
        return analysisInfo.kdjDiff > 0 || analysisInfo.isKdjIncrease
      case 'ema':
        return analysisInfo.ema5W10A20Days >= 1
      default:
        return false
    }
  }

  isIndicatorBearish (marketData, analysisData, timeframe, indicator) {
    const marketKey = `${indicator}${timeframe}Bad`
    if (marketData[marketKey] === true) return true

    const analysisInfo = analysisData[`analysisInfo${timeframe}`]
    if (!analysisInfo) return false

    switch (indicator) {
      case 'macd':
        return analysisInfo.macd < 0 && analysisInfo.macdDownDays >= 1
      case 'kdj':
        return analysisInfo.kdjDiff < 0 || analysisInfo.isKdjDecline
      case 'ema':
        return analysisInfo.ema5W10B20Days >= 1
      default:
        return false
    }
  }

  determineDirection (marketData, analysisData) {
    if (marketData.attack15m && !marketData.crash15m) {
      return 'BUY'
    } else if (marketData.crash15m && !marketData.attack15m) {
      return 'SELL'
    }

    const bullishSignals = this.countBullishSignals(marketData, analysisData)
    const bearishSignals = this.countBearishSignals(marketData, analysisData)

    return bullishSignals > bearishSignals ? 'BUY' : 'SELL'
  }

  countBullishSignals (marketData, analysisData) {
    let count = 0

    const bullishKeys = ['kdj15mGood', 'macd15mGood', 'ema15mGood', 'kdj1hGood', 'macd1hGood']
    count += bullishKeys.filter(key => marketData[key]).length;

    ['15m', '1h', '4h'].forEach(tf => {
      const analysisInfo = analysisData[`analysisInfo${tf}`]
      if (analysisInfo) {
        if (analysisInfo.macd > 0) count++
        if (analysisInfo.kdjDiff > 0) count++
        if (analysisInfo.ema5W10A20Days >= 1) count++
      }
    })

    return count
  }

  countBearishSignals (marketData, analysisData) {
    let count = 0

    const bearishKeys = ['kdj15mBad', 'macd15mBad', 'ema15mBad', 'kdj1hBad', 'macd1hBad']
    count += bearishKeys.filter(key => marketData[key]).length;

    ['15m', '1h', '4h'].forEach(tf => {
      const analysisInfo = analysisData[`analysisInfo${tf}`]
      if (analysisInfo) {
        if (analysisInfo.macd < 0) count++
        if (analysisInfo.kdjDiff < 0) count++
        if (analysisInfo.ema5W10B20Days >= 1) count++
      }
    })

    return count
  }

  getAlignedTimeframes (marketData, analysisData) {
    const timeframes = Object.keys(this.config.parameters.timeframes)

    return timeframes.filter(timeframe => {
      const indicators = Object.keys(this.config.parameters.indicators)
      const alignedCount = indicators.filter(indicator => {
        return this.isIndicatorAligned(marketData, analysisData, timeframe, indicator)
      }).length

      return alignedCount >= Math.ceil(indicators.length * 0.6)
    })
  }

  getAlignedIndicators (marketData, analysisData) {
    const indicators = Object.keys(this.config.parameters.indicators)

    return indicators.filter(indicator => {
      const alignedTimeframes = Object.keys(this.config.parameters.timeframes).filter(tf => {
        return this.isIndicatorAligned(marketData, analysisData, tf, indicator)
      })

      return alignedTimeframes.length >= this.config.parameters.minAlignedTimeframes
    })
  }

  checkDirectionalBias (marketData, analysisData) {
    const bullishSignals = this.countBullishSignals(marketData, analysisData)
    const bearishSignals = this.countBearishSignals(marketData, analysisData)
    const signalDifference = Math.abs(bullishSignals - bearishSignals)

    return signalDifference >= 2 // 至少2个信号的差异
  }

  classifyResonanceType (strength) {
    const { resonanceTypes } = this.config.parameters

    for (const [type, config] of Object.entries(resonanceTypes)) {
      if (strength >= config.minStrength) {
        return type
      }
    }

    return 'WEAK'
  }

  calculateConfidence (resonanceAnalysis) {
    let confidence = resonanceAnalysis.strength

    // 共振类型权重
    confidence *= resonanceAnalysis.typeConfig.weight

    // 时间框架数量加成
    confidence += Math.min(resonanceAnalysis.timeframes.length * 0.05, 0.2)

    // 指标数量加成
    confidence += Math.min(resonanceAnalysis.indicators.length * 0.05, 0.15)

    return Math.min(Math.max(confidence, 0), 1)
  }

  calculatePositionRate (resonanceAnalysis, confidence) {
    const baseRate = confidence * 0.7
    const typeMultiplier = resonanceAnalysis.typeConfig.positionMultiplier

    let adjustedRate = baseRate * typeMultiplier
    adjustedRate *= (0.5 + resonanceAnalysis.strength * 0.5)

    return Math.min(Math.max(adjustedRate, 0.1), 0.35)
  }

  calculateResonanceLevel (resonanceAnalysis) {
    switch (resonanceAnalysis.type) {
      case 'FULL':
      case 'STRONG':
        return 2
      case 'MODERATE':
        return 1
      default:
        return 0
    }
  }

  validateMarketData (marketData, analysisData) {
    if (!marketData || typeof marketData !== 'object') return false

    const requiredTimeframes = ['analysisInfo15m', 'analysisInfo1h', 'analysisInfo4h']
    return requiredTimeframes.every(tf => analysisData[tf])
  }
}

module.exports = MarketResonanceStrategy
